@using System.Collections.Immutable
@using System.ComponentModel.DataAnnotations
@using Humanizer
@using Passwordless.AdminConsole.Helpers
@using Passwordless.Common.Models.Apps
@inject ICurrentContext CurrentContext;
@inject NavigationManager NavigationManager;
@inject IHttpContextAccessor HttpContextAccessor;
@inject IScopedPasswordlessClient Passwordless;
@inject ILogger<AuthenticationConfiguration> Logger;

@if (!CurrentContext.IsPendingDelete)
{
    <Panel Header="Authentication Configuration">
        <p>List of configurations for your authentication tokens. Read more in the <a class="link-blue underline" href="https://docs.passwordless.dev/guide/admin-console/applications.html#authentication-configurations" target="_blank">docs</a></p>

        <div>
            <a class="btn-primary" href="/app/@(AppId)/settings/authentication-configuration/new">Add New Authentication Configuration</a>
        </div>

        <ConfirmEditForm FormName="@DeleteFormName" Model="ConfirmDeleteAuthenticationConfigurationModel" OnSubmit="@OnSelectedFormConfirmed">
            <Table ColumnHeaders="@(new[] { "Purpose", "User Verification", "Time To Live", "Credential Hints", "Last Used", "Actions" })" EmptyMessage="Something has failed. Please try refreshing.">
                @if (Configurations.Any())
                {
                    @foreach (var config in Configurations)
                    {
                        <tr>
                            <td>@config.Purpose</td>
                            <td>@config.UserVerification</td>
                            <td>@config.TimeToLive</td>
                            <td>@config.Hints</td>
                            <td>
                                @if (config.LastUsedOn.HasValue)
                                {
                                    <LocalDateTime Value="config.LastUsedOn.Value.UtcDateTime" DateFormat="g"/>
                                }
                            </td>
                            <td class="flex items-center space-x-2">
                                <a href="/app/@(AppId)/settings/authentication-configuration/@(config.Purpose)/edit">
                                    <PencilSquareIcon Class="h-6 w-6"></PencilSquareIcon>
                                </a>

                                @if (config.CanDelete)
                                {
                                    <ConfirmButton
                                        ConfirmTitle="Delete Authentication Configuration"
                                        ConfirmDescription="Are you sure you want to delete this configuration?"
                                        ConfirmButtonText="Delete"
                                        class="btn-danger flex items-center"
                                        name="ConfirmDeleteAuthenticationConfigurationModel.Purpose"
                                        type="submit"
                                        value="@config.Purpose">
                                        <DeleteIcon Class="h-6 w-6"></DeleteIcon>
                                    </ConfirmButton>
                                }
                            </td>
                        </tr>
                    }
                }
            </Table>
        </ConfirmEditForm>
    </Panel>
}

@code {
    private string AppId => CurrentContext.AppId!;

    public const string DeleteFormName = "delete-purpose-form";

    [SupplyParameterFromForm(FormName = DeleteFormName)]
    public ConfirmSelectedFormModel ConfirmDeleteAuthenticationConfigurationModel { get; set; } = new();

    private readonly IReadOnlyCollection<string> _requiredAuthenticationConfigurationNames = new[] { SignInPurpose.SignInName, SignInPurpose.StepUpName };

    private IReadOnlyCollection<AuthenticationConfigurationEntry> Configurations { get; set; } = [];

    public record AuthenticationConfigurationEntry(
        string Purpose,
        string UserVerification,
        string TimeToLive,
        string Hints,
        DateTimeOffset? LastUsedOn,
        bool CanDelete);

    private AuthenticationConfigurationEntry GetEntry(Common.Models.Apps.AuthenticationConfiguration configuration) =>
        new(configuration.Purpose,
            configuration.UserVerificationRequirement.Humanize(LetterCasing.Title),
            TimeSpan.FromSeconds(configuration.TimeToLive).Humanize(),
            string.Join(", ", configuration.Hints),
            configuration.LastUsedOn,
            _requiredAuthenticationConfigurationNames.All(x => !string.Equals(x, configuration.Purpose, StringComparison.OrdinalIgnoreCase)));

    protected override async Task OnInitializedAsync()
    {
        if (CurrentContext.IsPendingDelete) return;

        Configurations = await GetConfigurations();
    }


    private async Task<IReadOnlyCollection<AuthenticationConfigurationEntry>> GetConfigurations()
    {
        try
        {
            return (await Passwordless.GetAuthenticationConfigurationsAsync()).Configurations.Select(GetEntry).ToImmutableArray();
        }
        catch (Exception ex)
        {
            Logger.LogError(ex , "Failed to retrieve authentication configurations");
            return Array.Empty<AuthenticationConfigurationEntry>();
        }
    }

    public async Task OnSelectedFormConfirmed()
    {
        await Passwordless.DeleteAuthenticationConfigurationAsync(new DeleteAuthenticationConfigurationRequest
        {
            Purpose = ConfirmDeleteAuthenticationConfigurationModel.Purpose,
            PerformedBy = HttpContextAccessor.HttpContext!.User.GetName()
        });

        NavigationManager.NavigateTo($"app/{AppId}/settings");
    }

    public class ConfirmSelectedFormModel
    {
        [Required, MinLength(1), RegularExpression(@"^[\w\-\.]*$", ErrorMessage = "Characters are limited to A-z, 0-9, -, ., or _.")]
        public string Purpose { get; set; } = string.Empty;
    }
}